[FIX] hr_recruitment: fix lift_constraints() constraint drop order for PostgreSQL 17+ - #5884
Closed
quoc-pn wants to merge 1 commit into
Closed
Conversation
…r PostgreSQL 17+
On PostgreSQL 17+, NOT NULL is catalogued as a named constraint
(<table>_<column>_not_null) instead of an implicit attribute flag.
openupgrade.lift_constraints() drops all constraints on a column in a
single ALTER TABLE statement, listing the not-null constraint before
the primary key constraint. PostgreSQL validates each subcommand
against the pre-statement catalog state, so it refuses to drop the
not-null constraint while the column is still part of the primary
key, raising:
ERROR: column "id" is in a primary key
This happened when merging hr.candidate into hr.applicant and lifting
constraints on the renamed legacy table's id column.
Fix by dropping the primary key constraint on its own, in a separate
ALTER TABLE statement, before calling lift_constraints() for the
remaining not-null constraint.
quoc-pn
force-pushed
the
19.0-fix-hr_recruitment-lift_constraints-pg17
branch
from
August 5, 2026 08:00
b21bfcf to
f79477b
Compare
Member
|
Shouldn't this be fixed in openupgradelib instead? |
Member
Author
@pedrobaeza Thanks for the suggestion. I'll create a PR in openupgradelib. This PR will be closed once the corresponding PR in openupgradelib has been created. |
Member
Author
|
Closing this in favor of fixing the root cause upstream in openupgradelib itself: lift_constraints() combined all constraint drops into a single ALTER TABLE statement, which PostgreSQL 17+ rejects when a not-null constraint is listed before the primary key it depends on. See the fix at OCA/openupgradelib#462, which drops each constraint individually. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
On PostgreSQL 17+,
NOT NULLis catalogued as a named constraint (<table>_<column>_not_null) instead of an implicit attribute flag onpg_attribute.openupgrade.lift_constraints()drops all constraints on a column in a singleALTER TABLE ... DROP CONSTRAINT a, DROP CONSTRAINT bstatement. When the column has both a not-null constraint and a primary key, and the not-null constraint's drop clause is listed before the primary key's, PostgreSQL rejects the statement:PostgreSQL validates each
ALTER TABLEsubcommand against the catalog state before the statement runs, not against the pending effects of earlier subcommands in the same statement — so even though the very next clause would drop the primary key, the not-null drop is rejected first.This surfaced in
hr_recruitment/19.0.1.1/pre-migration.pywhen merginghr.candidateintohr.applicant: after renaminghr_candidateto its legacy table,lift_constraints(cr, legacy_table, "id", cascade=True)fails on PostgreSQL 17/18 with the error above.Fix
Drop the primary key constraint on the legacy table in its own, separate
ALTER TABLE ... DROP CONSTRAINT ... CASCADEstatement before callinglift_constraints(). By the timelift_constraints()runs, only the not-null constraint remains on the column, so there's no ordering conflict.Test
Reproduced the failure on a database running PostgreSQL 18.4 during an Odoo 19 upgrade, confirmed the fix resolves it.